#include "hero.h"

CHero::CHero(void)
{
	heroCoords = make_shared<CCoords>();
	cubeSize = make_shared<CCoords>();
}

CHero::~CHero(void)
{}

void CHero::parseMessage(Message& msg, vector<Message>& retMsg)
{
	switch(msg.MsgCode)
	{
	case MSG_INIT:
		{
			Message m("Hero","Cube",MSG_GET_SIZE);
			retMsg.push_back(m);
			heroCoords->set(0,1,0);
			m.Set("Hero","Cube",MSG_SET_CRSECTION,heroCoords);
			retMsg.push_back(m);
			m.Set("Hero","Cube",MSG_GET_CRSECTION);
			retMsg.push_back(m);
			break;
		}
	case MSG_UPDATE:
		{
			Message m("Hero","Keyboard",MSG_GET_PRESSED_KEYS);
			retMsg.push_back(m);
		}
		break;

	case MSG_PRESSED_KEYS:
		{
			Message m;
			PKeys k = dynamic_pointer_cast<CKeys>(msg.Data);

			if(k->keys.find('1')!=string::npos)
			{
				m.Set("Hero","Cube",MSG_GET_SIZE);
				retMsg.push_back(m);
				m.Set("Hero","Hero",MSG_ROT_LEFT);
				retMsg.push_back(m);
				m.Set("Hero","Cube",MSG_SET_CRSECTION,heroCoords);
				retMsg.push_back(m);
				m.Set("Hero","Cube",MSG_GET_CRSECTION);
				retMsg.push_back(m);
			}
			else if(k->keys.find('3')!=string::npos)
			{
				m.Set("Hero","Cube",MSG_GET_SIZE);
				retMsg.push_back(m);
				m.Set("Hero","Hero",MSG_ROT_RIGHT);
				retMsg.push_back(m);
				m.Set("Hero","Cube",MSG_SET_CRSECTION,heroCoords);
				retMsg.push_back(m);
				m.Set("Hero","Cube",MSG_GET_CRSECTION);
				retMsg.push_back(m);
			}
			else if(k->keys.find('9')!=string::npos)
			{
				m.Set("Hero","Cube",MSG_GET_SIZE);
				retMsg.push_back(m);
				m.Set("Hero","Hero",MSG_ROT_CLKWISE);
				retMsg.push_back(m);
				m.Set("Hero","Cube",MSG_SET_CRSECTION,heroCoords);
				retMsg.push_back(m);
				m.Set("Hero","Cube",MSG_GET_CRSECTION);
				retMsg.push_back(m);
			}
			else if(k->keys.find('7')!=string::npos)
			{
				m.Set("Hero","Cube",MSG_GET_SIZE);
				retMsg.push_back(m);
				m.Set("Hero","Hero",MSG_ROT_CCLKWISE);
				retMsg.push_back(m);
				m.Set("Hero","Cube",MSG_SET_CRSECTION,heroCoords);
				retMsg.push_back(m);
				m.Set("Hero","Cube",MSG_GET_CRSECTION);
				retMsg.push_back(m);
			}
			else if(k->keys.find('4')!=string::npos)
			{
				Move(MOV_LEFT);
			}
			else if(k->keys.find('6')!=string::npos)
			{
				Move(MOV_RIGHT);
			}
			else if(k->keys.find('8')!=string::npos)
			{
				Move(MOV_UP);
			}
		}
		break;

	case MSG_CUBE_SIZE:
		cubeSize->set(dynamic_pointer_cast<CCoords>(msg.Data));
		break;

	case MSG_CUBE_CRSECTION:
		crSection = dynamic_pointer_cast<CArray2D>(msg.Data);
		break;

	case MSG_ROT_LEFT:
		heroCoords->set(	cubeSize->getZ() - heroCoords->getZ() - 1,
							heroCoords->getY(), 
							heroCoords->getX());
		break;

	case MSG_ROT_RIGHT:
		heroCoords->set(	heroCoords->getZ(), 
							heroCoords->getY(), 
							cubeSize->getX() - heroCoords->getX() - 1);
		break;

	case MSG_ROT_CLKWISE:
		heroCoords->set(	heroCoords->getY(), 
							cubeSize->getX() - heroCoords->getX() - 1,
							heroCoords->getZ());
		break;

	case MSG_ROT_CCLKWISE:
		heroCoords->set(	cubeSize->getY() - heroCoords->getY() - 1,
							heroCoords->getX(),
							heroCoords->getZ());
		break;

	case MSG_DRAW_L0:
		{
			PArray2D disp = dynamic_pointer_cast<CArray2D>(msg.Data);
			int x = (disp->getXsize() - cubeSize->getX() )/2 + heroCoords->getX();
			int y = (disp->getYsize() - cubeSize->getY() )/2 + heroCoords->getY();
			(*disp)(x,y) = 'O';
		}
	}
}

void CHero::Move(int Dir)
{
	int x,y;
	switch(Dir)
	{
	case MOV_LEFT:
		{
			x = heroCoords->getX();
			y = heroCoords->getY();
			char c = (*crSection)(x-1,y);
			if(( c == ' ') || ( c == '.'))
				heroCoords->setX(x-1);
		}
		break;
	case MOV_RIGHT:
		{
			x = heroCoords->getX();
			y = heroCoords->getY();
			char c = (*crSection)(x+1,y);
			if(( c == ' ') || ( c == '.'))
				heroCoords->setX(x+1);
		}
		break;
	case MOV_UP:
		{
			x = heroCoords->getX();
			y = heroCoords->getY();
			char c = (*crSection)(x,y+1);
			if(( c == ' ') || ( c == '.'))
				heroCoords->setY(y+1);
		}
		break;
	case MOV_DOWN:
		{
			x = heroCoords->getX();
			y = heroCoords->getY();
			char c = (*crSection)(x,y-1);
			if(( c == ' ') || ( c == '.'))
				heroCoords->setY(y-1);
		}
		break;
	}
}